// =====================================================================================
//
//       Filename:  parser.cpp
//
//    Description:  Implémentation de fonctions générales pour l'interprétation des fichiers
//					d'entrée
//
//        Version:  1.0
//        Created:  25/08/2009 17:03:25
//       Revision:  none
//       Compiler:  g++
//
//         Author:  François Hissel (fh), francois.hissel@m4x.org
//        Company:
//
// =====================================================================================

#include	<iostream>
#include	<sstream>
#include	<string>
#include	"parser.h"

using namespace std;

/**********************************************/
/* IMPLEMENTATION DE LA CLASSE PARSEEXCEPTION */
/**********************************************/
const char* ParseException::what() const throw() {
	switch (code) {
		case FORMAT_ERROR:return ("Erreur de format : "+message).c_str();
		default:return message.c_str();
	}
}

/*****************************************/
/* IMPLEMENTATION DES FONCTIONS PUBLIEES */
/*****************************************/
int getint(const string &line,size_t &pos,char delim) throw (ParseException) {
	pos=line.find_first_not_of(' ',pos);
	if (pos>=line.length()) throw ParseException(ParseException::FORMAT_ERROR);
	size_t fin=line.find_first_of(delim,pos);
	if (fin==string::npos) fin=line.length();
	if (fin==pos) return -1;
	istringstream iss(line.substr(pos,fin-pos));
	pos=fin+1;
	int result;
	try {
		iss >> result;
	} catch (exception) {
		throw ParseException(ParseException::FORMAT_ERROR);
	}
	return result;
}

double getfloat(const string &line,size_t &pos,char delim) throw (ParseException) {
	pos=line.find_first_not_of(' ',pos);
	if (pos>=line.length()) throw ParseException(ParseException::FORMAT_ERROR);
	size_t fin=line.find_first_of(delim,pos);
	if (fin==string::npos) fin=line.length();
	if (fin==pos) return -1.0;
	istringstream iss(line.substr(pos,fin-pos));
	pos=fin+1;
	double result;
	try {
		iss >> result;
	} catch (exception) {
		throw ParseException(ParseException::FORMAT_ERROR);
	}
	return result;
}

string getstring(const string &line,size_t &pos,char delim) throw (ParseException) {
	pos=line.find_first_not_of(' ',pos);
	if (pos>=line.length()) throw ParseException(ParseException::FORMAT_ERROR);
	bool sep=true;	// Variable qui indique si on a rencontré le délimiteur final, dans le cas où la chaîne est délimitée en plus par des guillemets.
	bool fin=false;	// Variable qui indique si on a passé le séparateur final, représenté par le caractère delim
	if (line[pos]=='"') {
		sep=false;
		++pos;
	}
	ostringstream iss("");
	while (!fin || !sep) {
		if (pos>=line.length()) {
			if (sep) fin=true;
			else throw ParseException(ParseException::FORMAT_ERROR,"Mauvais format de chaîne de caractères");
			continue;
		}
		if (!sep && line[pos]=='"') {
			if (pos+1>=line.length() || line[pos+1]!='"') sep=true; else {
				if (line[pos+1]=='"') iss << '"';
				++pos;
			}
		} else if (sep && line[pos]==delim) fin=true;
		else if (line[pos]!='\n' && line[pos]!='\r') iss << line[pos];	// On n'ajoute pas les sauts de ligne à la fin de la chaîne s'il y en a (compatibilité Windows).
		++pos;
	}
	return iss.str();
}

bool string_compare(const string &s1,const string &s2,size_t debut,size_t longueur) {
	size_t i=0;size_t j=debut;
	bool ok=true;
	while (ok && i<longueur && i<s1.length() && j<s2.length()) if (toupper(s1[i++])!=toupper(s2[j++])) ok=false;
	return (ok && i==longueur);
}

bool string_compare(const string &s1,const string &s2) {
	if (s2.length()==s1.length()) return string_compare(s1,s2,0,s1.length()); else return false;
}

string trim(const string& s) {
	size_t i=0;
	while (i<s.length() && isspace(s[i])) ++i;
	size_t j=s.length()-1;
	while (j>=0 && isspace(s[j])) --j;
	if (i<s.length() && j>=0) return s.substr(i,j-i+1); else return "";
}
